﻿/* Copyright 2010 Igor Francé
 * 
 * This file is part of ECMADoc (http://ecmadoc.codeplex.com).
 * 
 * ECMADoc is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License 
 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * ECMADoc is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with ECMADoc. 
 * If not, see http://www.gnu.org/licenses/.
 */
namespace EcmaDoc.Core.Output
{
	using System;
	using System.Collections.Generic;
	using System.IO;
	using System.Text.RegularExpressions;
	using System.Xml;

	using Configuration;
	using Transform;
	using Transform.Extensions;

	internal class TransformPackage
	{
		/// <summary>
		/// Defines the path of the directory that contains the xslt transforms.
		/// </summary>
		public const string XsltPath = @"Resources\Transforms";

		internal TransformPackage(Project project)
		{
			this.Project = project;

			XsltProject = PrepareTransform("project");
			XsltContents = PrepareTransform("contents");
			XsltDefault = PrepareTransform("default");
			XsltIndex = PrepareTransform("index");
			XsltNamespace = PrepareTransform("namespace");
			XsltDocument = PrepareTransform("document");
			XsltObject = PrepareTransform("object");
		}

		internal XsltTransform XsltContents
		{
			get; 
			private set;
		}

		internal XsltTransform XsltDefault
		{
			get;
			private set;
		}

		internal XsltTransform XsltIndex
		{
			get;
			private set;
		}

		internal XsltTransform XsltNamespace
		{
			get;
			private set;
		}

		internal XsltTransform XsltDocument
		{
			get;
			private set;
		}

		internal XsltTransform XsltObject
		{
			get;
			private set;
		}

		internal XsltTransform XsltProject
		{
			get;
			private set;
		}

		internal string ThemePath
		{
			get
			{
				return Path.Combine(Path.Combine(TransformPackage.XsltPath, "Themes"), Project.Info.Theme);
			}
		}

		private Project Project { get; set; }

		internal void Transform(XsltTransform transformer, XmlNode project, XmlNode subject, string path)
		{
			Transform(transformer, project, subject, path, null);
		}

		internal void Transform(XsltTransform transformer, XmlNode project, XmlNode subject, string path, Dictionary<string, object> transformParams)
		{
			Dictionary<string, object> parameters = new Dictionary<string, object>();
			parameters.Add("themeName", this.Project.Info.Theme);
			parameters.Add("transformSubject", subject);

			if (transformParams != null)
			{
				foreach (string name in transformParams.Keys)
				{
					if (transformParams[name] != null)
					{
						if (parameters.ContainsKey(name))
							parameters[name] = transformParams[name];
						else
							parameters.Add(name, transformParams[name]);
					}
				}
			}

			using (FileStream output = new FileStream(path, FileMode.Create))
			{
				transformer.TransformToStream(project, output, parameters, true);
			}		
		}
		
		internal void CopyResources()
		{
			string sourcePath = Utilities.ExpandPath(ThemePath);
			CopyResources(sourcePath, Project.Info.OutputPathFull);
		}

		private void CopyResources(string source, string destination)
		{
			CopyResources(source, destination, new[] { @"\.xslt$", @"\.svn$" });
		}

		private void CopyResources(string source, string destination, IEnumerable<string> excludePatterns)
		{
			if (!Directory.Exists(destination))
			{
				Directory.CreateDirectory(destination);
			}

			string[] entries = Directory.GetFileSystemEntries(source);
			foreach (string entry in entries)
			{
				bool exclude = false;
				foreach (string  pattern in excludePatterns)
				{
					if (Regex.Match(entry, pattern).Success)
					{
						exclude = true;
						break;
					}
				}
				if (exclude)
					continue;

				FileAttributes attrib = File.GetAttributes(entry);
				if ((attrib & FileAttributes.Hidden) == FileAttributes.Hidden)
					continue;

				string destinationFile = Path.Combine(destination, Path.GetFileName(entry));
				if (Directory.Exists(entry))
					CopyResources(entry, destinationFile, excludePatterns);
				else
					File.Copy(entry, destinationFile, true);
			}
		}

		private XsltTransform PrepareTransform(string transformName)
		{
			string path = Path.Combine(ThemePath, string.Concat(transformName, ".xslt"));

			XsltTransform transform = new XsltTransform(Utilities.ExpandPath(path));
			transform.AddArgument("transformName", transformName.ToLower());
			transform.AddArgument("projectName", this.Project.Info.Name);
			transform.AddArgument("themeName", this.Project.Info.Theme);

			transform.AddExtensionObject(ParserConfig.EcmaDocNamespace, this.Project);
			transform.AddExtensionObject(MathExtensions.Namespace, new MathExtensions());
			transform.AddExtensionObject(TransformHelper.Namespace, new TransformHelper());
			
			return transform;
		}
	}
}
